package com.wang.gallerybackend.service.impl;

import 	cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wang.gallerybackend.exception.BusinessException;
import com.wang.gallerybackend.exception.ErrorCode;
import com.wang.gallerybackend.exception.ThrowUtils;
import com.wang.gallerybackend.mapper.SpaceMapper;
import com.wang.gallerybackend.model.dto.space.analyze.*;
import com.wang.gallerybackend.model.entity.Picture;
import com.wang.gallerybackend.model.entity.Space;
import com.wang.gallerybackend.model.entity.User;
import com.wang.gallerybackend.model.vo.space.SpaceUserAnalyzeResponse;
import com.wang.gallerybackend.model.vo.space.analyze.SpaceCategoryAnalyzeResponse;
import com.wang.gallerybackend.model.vo.space.analyze.SpaceSizeAnalyzeResponse;
import com.wang.gallerybackend.model.vo.space.analyze.SpaceTagAnalyzeResponse;
import com.wang.gallerybackend.model.vo.space.analyze.SpaceUsageAnalyzeResponse;
import com.wang.gallerybackend.service.PictureService;
import com.wang.gallerybackend.service.SpaceAnalyzeService;
import com.wang.gallerybackend.service.SpaceService;
import com.wang.gallerybackend.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SpaceAnalyzeServiceImpl extends ServiceImpl<SpaceMapper, Space>
		implements SpaceAnalyzeService {

	@Resource
	private UserService userService;
	@Resource
	private SpaceService spaceService;
	@Resource
	private PictureService pictureService;


	@Override
	public SpaceUsageAnalyzeResponse spaceUsageAnalyze(SpaceUsageAnalyzeRequest spaceUsageAnalyzeRequest, User loginUser) {
		// 校验参数

		// 全空间和公共空间需要从Picture表获取
		if (spaceUsageAnalyzeRequest.isQueryAll() || spaceUsageAnalyzeRequest.isQueryPublic()) {
			//权限校验
			checkSpaceAnalyzeAuth(spaceUsageAnalyzeRequest, loginUser);
			//统计公共图库的使用
			QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
			queryWrapper.select("picSize");
			fillAnalyzeQueryWrapper(spaceUsageAnalyzeRequest, queryWrapper);
			List<Object> picObjList = pictureService.getBaseMapper().selectObjs(queryWrapper);
			long picSize = picObjList.stream().mapToLong(obj -> (Long) obj).sum();
			long userCount = picObjList.size();
			//封装返回结果
			SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
			spaceUsageAnalyzeResponse.setUsedSize(picSize);
			spaceUsageAnalyzeResponse.setUsedCount(userCount);
			return spaceUsageAnalyzeResponse;
		} else {
			// 特定空间可以从Space表进行查询
			Long spaceId = spaceUsageAnalyzeRequest.getSpaceId();
			ThrowUtils.throwIf(spaceId == null || spaceId < 0, ErrorCode.PARAMS_ERROR);
			Space space = spaceService.getById(spaceId);
			ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR);
			spaceService.checkSpaceAuth(loginUser, space);
			//封装返回结果
			SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
			spaceUsageAnalyzeResponse.setUsedSize(space.getTotalSize());
			spaceUsageAnalyzeResponse.setUsedCount((long) space.getTotalCount());
			spaceUsageAnalyzeResponse.setMaxSize(space.getMaxSize());
			spaceUsageAnalyzeResponse.setMaxCount(space.getMaxCount());
			spaceUsageAnalyzeResponse.setSizeUsageRatio(
					NumberUtil.round(spaceUsageAnalyzeResponse.getUsedSize() * 100.0
							/ spaceUsageAnalyzeResponse.getMaxSize(), 2).doubleValue());
			spaceUsageAnalyzeResponse.setCountUsageRatio(NumberUtil.round(spaceUsageAnalyzeResponse.getUsedCount() * 100.0
					/ spaceUsageAnalyzeResponse.getMaxCount(), 2).doubleValue());
			return spaceUsageAnalyzeResponse;
		}
	}

	@Override
	public List<SpaceCategoryAnalyzeResponse> getSpaceCategoryAnalyze(SpaceCategoryAnalyzeRequest spaceCategoryAnalyzeRequest, User loginUser) {
		ThrowUtils.throwIf(spaceCategoryAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
		// 检查权限
		checkSpaceAnalyzeAuth(spaceCategoryAnalyzeRequest, loginUser);
		// 统计
		QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
		fillAnalyzeQueryWrapper(spaceCategoryAnalyzeRequest, queryWrapper);
		//使用Mybatis-plus分组查询
		queryWrapper.select("category", "count(1) as count", "sum(picSize) as totalSize")
				.groupBy("category");
		return pictureService.getBaseMapper().selectMaps(queryWrapper).stream().map(result -> {
			String category = (String) result.get("category");
			Long count = ((Number) result.get("count")).longValue();
			Long totalSize = ((Number) result.get("totalSize")).longValue();
			return new SpaceCategoryAnalyzeResponse(category, count, totalSize);
		}).collect(Collectors.toList());
	}

	@Override
	public List<SpaceTagAnalyzeResponse> getSpaceTagAnalyze(SpaceTagAnalyzeRequest spaceTagAnalyzeRequest, User loginUser) {

		ThrowUtils.throwIf(spaceTagAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
		// 检查权限
		checkSpaceAnalyzeAuth(spaceTagAnalyzeRequest, loginUser);
		// 统计
		QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
		fillAnalyzeQueryWrapper(spaceTagAnalyzeRequest, queryWrapper);
		//使用Mybatis-plus分组查询
		queryWrapper.select("tags");
		List<String> tagJsonList = pictureService.getBaseMapper()
				.selectObjs(queryWrapper)
				.stream().filter(ObjUtil::isNotEmpty)
				.map(Object::toString).collect(Collectors.toList());
		//解析tagJson并统计
		Map<String, Long> tagCountMap = tagJsonList.stream()
				.flatMap(tagjson -> JSONUtil.toList(tagjson, String.class).stream()).collect(
						Collectors.groupingBy(tag -> tag, Collectors.counting()));
		//转化为响应对象，按照使用次数进行排序
		return tagCountMap
				.entrySet().stream().sorted((e1, e2) -> Long.compare(e2.getValue(), e1.getValue()))
				.map(entry -> new SpaceTagAnalyzeResponse(entry.getKey(), entry.getValue()))
				.collect(Collectors.toList());
	}

	@Override
	public List<SpaceSizeAnalyzeResponse> getSpaceSizeAnalyze(SpaceSizeAnalyzeRequest spaceTagAnalyzeRequest, User loginUser) {
		ThrowUtils.throwIf(spaceTagAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
		// 检查权限
		checkSpaceAnalyzeAuth(spaceTagAnalyzeRequest, loginUser);
		// 统计
		QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
		fillAnalyzeQueryWrapper(spaceTagAnalyzeRequest, queryWrapper);
		//使用Mybatis-plus分组查询
		queryWrapper.select("picSize");
		List<Long> picSizeList = pictureService.getBaseMapper()
				.selectObjs(queryWrapper)
				.stream()
				.filter(ObjUtil::isNotEmpty)
				.map(size -> (Long) size)
				.collect(Collectors.toList());
		// 定义分段范围，注意使用有序的 Map
		Map<String, Long> sizeRanges = new LinkedHashMap<>();
		sizeRanges.put("<100KB", picSizeList.stream().filter(size -> size < 100 * 1024).count());
		sizeRanges.put("100KB-500KB", picSizeList.stream().filter(size -> size >= 100 * 1024 && size < 500 * 1024).count());
		sizeRanges.put("500KB-1MB", picSizeList.stream().filter(size -> size >= 500 * 1024 && size < 1 * 1024 * 1024).count());
		sizeRanges.put(">1MB", picSizeList.stream().filter(size -> size >= 1 * 1024 * 1024).count());

		// 转换为响应对象
		return sizeRanges.entrySet().stream()
				.map(entry -> new SpaceSizeAnalyzeResponse(entry.getKey(), entry.getValue()))
				.collect(Collectors.toList());
	}

	@Override
	public List<SpaceUserAnalyzeResponse> getSpaceUserAnalyze(SpaceUserAnalyzeRequest spaceUserAnalyzeRequest, User loginUser) {
		ThrowUtils.throwIf(spaceUserAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
		// 检查权限
		checkSpaceAnalyzeAuth(spaceUserAnalyzeRequest, loginUser);
		// 统计
		QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
		fillAnalyzeQueryWrapper(spaceUserAnalyzeRequest, queryWrapper);
		//补充用户id查询
		Long userId = spaceUserAnalyzeRequest.getUserId();
		queryWrapper.eq(ObjUtil.isNotNull(userId), "userId", userId);
		//分析维度
		String timeDimension = spaceUserAnalyzeRequest.getTimeDimension();
		switch (timeDimension) {
			case "day":
				queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m-%d') as period", "count(*) as count");
				break;
			case "week":
				queryWrapper.select("YEARWEEK(createTime) as period", "count(*) as count");
				break;
			case "month":
				queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m') as period", "count(*) as count");
				break;
			default:
				throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的时间维度");
		}

		// 分组排序
		queryWrapper.groupBy("period").orderByAsc("period");

		// 查询并封装结果
		List<Map<String, Object>> queryResult = pictureService.getBaseMapper().selectMaps(queryWrapper);
		return queryResult
				.stream()
				.map(result -> {
					String period = result.get("period").toString();
					Long count = ((Number) result.get("count")).longValue();
					return new SpaceUserAnalyzeResponse(period, count);
				})
				.collect(Collectors.toList());
	}

	@Override
	public List<Space> getSpaceRankAnalyze(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest, User loginUser) {
		ThrowUtils.throwIf(spaceRankAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
		ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NOT_AUTH_ERROR);
		QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
		queryWrapper.select("id", "spaceName", "userId", "totalSize").orderByDesc("totalSize")
				.last("limit "+spaceRankAnalyzeRequest.getTopN());
		return spaceService.list(queryWrapper);
	}

	/**
	 * 校验空间权限
	 * @param spaceAnalyzeRequest
	 * @param loginUser
	 */
	private void checkSpaceAnalyzeAuth(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {

		boolean queryAll = spaceAnalyzeRequest.isQueryAll();
		boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
		//全空间分析和公开空间分析需要管理员权限
		if (queryAll || queryPublic) {
			ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NOT_AUTH_ERROR);
		} else {
			//仅本人或者管理员可查询
			Long spaceId = spaceAnalyzeRequest.getSpaceId();
			if (spaceId == null) {
				throw new BusinessException(ErrorCode.PARAMS_ERROR);
			}
			Space space = spaceService.getById(spaceId);
			ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR);
			//校验是否有公共权限
			spaceService.checkSpaceAuth(loginUser, space);

		}
	}


	/**
	 * 根据请求对象封装查询条件
	 *
	 * @param spaceAnalyzeRequest
	 * @param queryWrapper
	 */
	private void fillAnalyzeQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest, QueryWrapper<Picture> queryWrapper) {
		// 全空间分析
		boolean queryAll = spaceAnalyzeRequest.isQueryAll();
		if (queryAll) {
			return;
		}
		// 公共图库
		boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
		if (queryPublic) {
			queryWrapper.isNull("spaceId");
			return;
		}
		// 分析特定空间
		Long spaceId = spaceAnalyzeRequest.getSpaceId();
		if (spaceId != null) {
			queryWrapper.eq("spaceId", spaceId);
			return;
		}
		throw new BusinessException(ErrorCode.PARAMS_ERROR, "未指定查询范围");
	}


}
